﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
using System.Reflection;

namespace SQLI.UlsViewer
{
    /// <summary>
    /// A class that encapsulates loading animation behavioral attributes with bounded UI control for long running operations.
    /// </summary>
    public static class LoadingAnimator
    {
        private static bool isAnimate;
        private delegate void PaintControlEventHandler(object sender);
        private static Control control;

        /// <summary>
        /// Initializes the static variables defined.
        /// </summary>
        static LoadingAnimator()
        {

           
           Image = global::SQLI.UlsViewer.Properties.Resources.loading1;

           // Image = Bitmap.FromFile(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), @"Resources\loading.gif")); 
            // Bitmap.FromFile(@"..\..\Resources\loading.gif");
            isAnimate = true;
        }

        /// <summary>
        /// Wires the control with the loading indicator and starts the animation.
        /// </summary>
        /// <param name="ctrl">Any UI Control that requires long running operations to perform.</param>
        public static void Wire(Control ctrl)
        {
            control = ctrl;
            isAnimate = true;
            Cursor.Current = Cursors.Default;
            AnimateLoading();
        }

        /// <summary>
        /// Unwires the control from the loading indicator and stops the animation.
        /// </summary>
        /// <param name="ctrl">Any UI Control that requires long running operations to perform.</param>
        public static void UnWire(Control ctrl)
        {
            control = ctrl;
            isAnimate = false;
        }

        /// <summary>
        /// Gets or Sets Animated Image(with multiple frames).
        /// </summary>
        public static Image Image
        {
            get;
            set;
        }

        /// <summary>
        /// A method that initiates the loading animation.
        /// </summary>
        private static void AnimateLoading()
        {
            ImageAnimator.Animate(Image, new EventHandler(RaiseControlPaint));
        }

        /// <summary>
        /// A method that paints the loading indicator over the wired control.
        /// </summary>
        /// <param name="sender">Wired Control.</param>
        private static void PaintControl(object sender)
        {
            Control ctrl = sender as Control;
            if (isAnimate)
            {
                using (Graphics gr = ctrl.CreateGraphics())
                {
                    ImageAnimator.UpdateFrames(Image);
                    gr.DrawImage(Image, new Point(ctrl.Bounds.Width / 2, ctrl.Bounds.Height / 2));
                }
            }
        }

        /// <summary>
        /// A method that invokes the loading animation aside during long running operation in wired control.
        /// </summary>
        /// <param name="o">sender</param>
        /// <param name="e">event argument</param>
        private static void RaiseControlPaint(object o, EventArgs e)
        {
            if (control != null && !control.IsDisposed)
            {
                if (control.InvokeRequired)
                {
                    PaintControlEventHandler handler = new PaintControlEventHandler(PaintControl);
                    IAsyncResult result = handler.BeginInvoke(control, null, null);
                    handler.EndInvoke(result);
                }
                else
                {
                    control.Invalidate(true);
                }
            }
        }
    }
}
